import datetime
import logging
from google.appengine.ext import db
from models import SolarArray
from models import SolarData
from models import SolarDay
from models import SolarAggregate
from utils import toTZ
from utils import roundDt

INTERVAL = 15
INTERVAL_DELTA = datetime.timedelta(minutes = INTERVAL)
def getDayInfo(system, days, now):
  kwhNowDate = lambda day: getKey(system, datetime.datetime(day.year, day.month, day.day, now.hour, now.minute, now.second, 0, now.tzinfo), INTERVAL)
  kwhEndOfDay = lambda day: getKey(system, datetime.datetime(day.year, day.month, day.day, 21, 15, 0, 0, now.tzinfo), INTERVAL)
  aggs = SolarAggregate.get_by_key_name(map(kwhNowDate, days) + map(kwhEndOfDay, days), parent = system)
  logging.debug(aggs)
  data = [ x != None and x.kwhToday or 0 for x in aggs]
  return (data[:len(days)], data[len(days):])

def getKey(system, date, interval):
  return '%s:%s:%d' % (system.key(), date, interval)
  
def getAggregates(system, now, start, expectedRecords, tz):
  now = roundDt(now)
  start = roundDt(start) - INTERVAL_DELTA
  aggregate = SolarAggregate.all()
  aggregate.order('-date')
  aggregate.filter('system =',system.key())
  aggregate.filter('date >=', start)
  aggregate.filter('length =', INTERVAL)
  agg = aggregate.fetch(expectedRecords)
  new = []
  old = []
  logging.debug('wanted %d, got %d' % (expectedRecords, len(agg)))
  if len(agg) < expectedRecords:
    startDate = (len(agg) > 0 and toTZ(agg[0].date, tz) or start) - INTERVAL_DELTA
    endDate = now
    bucketEnd = endDate - INTERVAL_DELTA
    data = SolarData.all().filter('system =',system.key()).order('-date').filter('date >', startDate).filter('date <', endDate)
    new = aggregateData(data, endDate, system, tz)
    agg = new + agg
  if len(agg) < expectedRecords:
    startDate = start - INTERVAL_DELTA
    endDate = len(agg) > 0 and (toTZ(agg[-1].date, tz) - INTERVAL_DELTA) or now
    bucketEnd = endDate + INTERVAL_DELTA
    data = SolarData.all().filter('system =',system.key()).order('-date').filter('date >', startDate).filter('date <', endDate)
    old = aggregateData(data, bucketEnd, system, tz)
    agg.extend(old)
  if len(new) + len(old) > 0:    
    db.put(new + old)
  logging.debug('returning %d rows' % len(agg))
  return agg 
  
def aggregateData(data, endDate, system, tz):  
  kwh = 0.0
  maxWatts = 0
  count = 0
  total = 0
  new = []
  old = []
  rows = 0
  bucketEnd = endDate - INTERVAL_DELTA
  for d in data:
    dateTZ = toTZ(d.date, tz)
    #logging.debug('processing %s' % dateTZ)
    rows += 1
    if dateTZ < bucketEnd:
      if count > 0:
        key = getKey(system, endDate, INTERVAL)
        logging.debug('adding bucket, key=%s, count=%d, total=%d, watts=%d' % (key, count, total, total / count) )
        a = SolarAggregate(key_name = key,
                          parent = system,
                          date = endDate, 
                          length = INTERVAL,
                          system = system, 
                          kwhToday = kwh, 
                          maxWatts = maxWatts,
                          watts = total / count,
                          points = count) 
        new.append(a)
      kwh = 0.0
      maxWatts = 0
      total = 0
      count = 0
      endDate = bucketEnd
      bucketEnd = endDate - INTERVAL_DELTA
    if dateTZ > bucketEnd and dateTZ < endDate:
      if d.watts > maxWatts:
        maxWatts = d.watts
      if d.kwhToday > kwh:
        kwh = d.kwhToday
      count += 1
      total += d.watts
  logging.debug('processed %d data rows' % rows)
  return new